import 'package:flutter/foundation.dart';

///通过静态变量proxy，在widget build的时候与状态绑定
///定义一个观察者，观察RxObj<T>的数据变化，并通知UI更新
class RxObserver<T> {
  ///观察数据变化方法回调
  VoidCallback? update;

  ///判断当前widget是否具备刷新能力（Obz）
  bool get canUpdate => update != null;

  ///关闭
  void close() {
    update = null;
  }

  ///注意：obz变量与Obz控件建立联系
  static RxObserver? proxy;

  ///观察事件的变化
  observe(VoidCallback update) {
    this.update = update;
  }
}

///RxObj类，所有数据类型可通过.obz扩展属性获得此示例
///当value发生变化时，通知RxObserver更新UI
class RxObj<T> {
  late T _value;

  bool _firstRebuild = true;

  final List<RxObserver> _observers = [];

  RxObj(this._value);

  T get value {
    if (RxObserver.proxy != null) {
      _observers.add(RxObserver.proxy!);
    }
    return _value;
  }

  set value(T val) {
    if (_value == val && _firstRebuild) {
      return;
    }

    _firstRebuild = false;
    _value = val;

    //数据变化的时候，更新UI
    refresh();
  }

  ///刷新UI，使用引用数据类型的时候，如果没有调用set方法，需要手动refresh()一下
  void refresh() {
    if (_observers.isNotEmpty) {
      for (var observer in _observers) {
        if (observer.canUpdate) {
          observer.update!();
        }
      }
    }
  }
}

///RxObj扩展属性
extension RxT<T> on T {
  ///返回RxObj实例，使用.obz
  RxObj<T> get obz => RxObj<T>(this);
}
